/**
 * 滚动条锁定工具类 - 终极优化版
 * 使用 position: fixed 方案，完美解决滚动条抖动问题
 */

// 滚动条宽度缓存
let cachedScrollbarWidth: number | null = null;

/**
 * 获取滚动条宽度
 */
function getScrollbarWidth(): number {
  if (cachedScrollbarWidth !== null) return cachedScrollbarWidth;

  const outer = document.createElement("div");
  outer.style.cssText =
    "visibility:hidden;overflow:scroll;position:absolute;top:-9999px;width:100px;height:100px";
  document.body.appendChild(outer);

  const inner = document.createElement("div");
  inner.style.width = "100%";
  outer.appendChild(inner);

  cachedScrollbarWidth = outer.offsetWidth - inner.offsetWidth;
  document.body.removeChild(outer);

  return cachedScrollbarWidth;
}

class ScrollLock {
  private lockCount: number = 0;
  private originalStyles: {
    overflow: string;
    position: string;
    top: string;
    width: string;
    paddingRight: string;
    left: string;
    right: string;
  } | null = null;
  private scrollPosition: number = 0;

  /**
   * 锁定滚动
   * 使用 position: fixed + overflow-y: scroll 保持滚动条可见
   */
  lock(): void {
    this.lockCount++;

    // 已经锁定，不重复操作
    if (this.lockCount > 1) return;

    const hasScrollbar =
      document.documentElement.scrollHeight > window.innerHeight;

    if (!hasScrollbar) {
      // 没有滚动条，只需要禁止滚动
      this.originalStyles = {
        overflow: document.body.style.overflow,
        position: document.body.style.position,
        top: document.body.style.top,
        width: document.body.style.width,
        paddingRight: document.body.style.paddingRight,
        left: document.body.style.left,
        right: document.body.style.right,
      };
      document.body.style.overflow = "hidden";
      return;
    }

    // 保存当前滚动位置
    this.scrollPosition =
      window.pageYOffset || document.documentElement.scrollTop;

    // 计算滚动条宽度
    const scrollbarWidth = getScrollbarWidth();
    const currentPadding =
      parseInt(window.getComputedStyle(document.body).paddingRight) || 0;

    // 保存原始样式
    this.originalStyles = {
      overflow: document.body.style.overflow,
      position: document.body.style.position,
      top: document.body.style.top,
      width: document.body.style.width,
      paddingRight: document.body.style.paddingRight,
      left: document.body.style.left,
      right: document.body.style.right,
    };

    // 使用 cssText 一次性设置所有样式，确保原子操作
    const currentCssText = document.body.style.cssText;
    document.body.style.cssText = `
      ${currentCssText}
      position: fixed !important;
      top: -${this.scrollPosition}px !important;
      left: 0 !important;
      right: 0 !important;
      width: 100% !important;
      overflow-y: scroll !important;
      padding-right: ${currentPadding + scrollbarWidth}px !important;
    `;
  }

  /**
   * 解锁滚动
   */
  unlock(): void {
    this.lockCount = Math.max(0, this.lockCount - 1);

    // 还有其他锁定，不解锁
    if (this.lockCount > 0) return;

    // 恢复原始样式
    if (this.originalStyles) {
      const scrollY = this.scrollPosition;

      document.body.style.position = this.originalStyles.position;
      document.body.style.top = this.originalStyles.top;
      document.body.style.left = this.originalStyles.left;
      document.body.style.right = this.originalStyles.right;
      document.body.style.width = this.originalStyles.width;
      document.body.style.overflow = this.originalStyles.overflow;
      document.body.style.paddingRight = this.originalStyles.paddingRight;

      // 恢复滚动位置
      window.scrollTo(0, scrollY);

      this.originalStyles = null;
      this.scrollPosition = 0;
    }
  }

  /**
   * 强制解锁
   */
  forceUnlock(): void {
    this.lockCount = 0;
    this.unlock();
  }

  /**
   * 检查锁定状态
   */
  isLocked(): boolean {
    return this.lockCount > 0;
  }

  /**
   * 获取锁定计数
   */
  getLockCount(): number {
    return this.lockCount;
  }
}

// 创建单例
const scrollLock = new ScrollLock();

// 页面卸载时清理
if (typeof window !== "undefined") {
  window.addEventListener("beforeunload", () => {
    scrollLock.forceUnlock();
  });
}

export default scrollLock;
export { scrollLock };
